Capital Asset Pricing Model (CAPM)


In [1]:
%matplotlib inline

In [2]:
# Make the plots larger
from IPython.core.pylabtools import figsize
figsize(15, 5)

In [3]:
import pandas as pd
import pandas.io.data as web
from matplotlib import pyplot as plt

Get stock prices for Google, Apple, Marcosoft and Facebook during 2013-01-01 - 2013-12-31


In [4]:
prices = web.get_data_yahoo(['GOOGL', 'AAPL', 'MSFT', 'FB'], start='2013-01-01', end='2013-12-31')['Adj Close']
prices.head()


Out[4]:
AAPL FB GOOGL MSFT
Date
2013-01-02 529.43 28.00 361.99 26.42
2013-01-03 522.75 27.77 362.20 26.07
2013-01-04 508.19 28.76 369.35 25.58
2013-01-07 505.20 29.42 367.74 25.53
2013-01-08 506.56 29.06 367.02 25.40

5 rows × 4 columns


In [5]:
prices.plot()


Out[5]:
<matplotlib.axes.AxesSubplot at 0x7fd2863b2510>

Get qoutes of S&P 500 during 2013-01-01 - 2013-12-31


In [6]:
gspc = web.get_data_yahoo('^GSPC', start='2013-01-01', end='2013-12-31')['Adj Close']
gspc.name = '^GSPC'
gspc.head()


Out[6]:
Date
2013-01-02    1462.42
2013-01-03    1459.37
2013-01-04    1466.47
2013-01-07    1461.89
2013-01-08    1457.15
Name: ^GSPC, dtype: float64

Get risk free rate


In [7]:
risk_free_rate = web.get_quote_yahoo('^TNX')['last'][0] / 100
risk_free_rate


Out[7]:
0.02597

In [8]:
daily_risk_free_rate = (1 + risk_free_rate) ** (1 / len(gspc)) - 1
daily_risk_free_rate


Out[8]:
0.00010174528107698144

In [9]:
def capm_analysis(stock, index, risk_free_rate, window=None):    
    stock_ret = stock.pct_change().dropna()
    index_ret = index.pct_change().dropna()
    stock_premium = stock_ret - risk_free_rate
    index_premium = index_ret - risk_free_rate
    window = window or len(index_ret)
    betas =  pd.ols(y=stock_premium, x=index_premium, window=window).beta
    return betas.rename(columns={'x': 'beta', 'intercept': 'alpha'})

In [10]:
capm_analysis(prices['GOOGL'], gspc, daily_risk_free_rate).iloc[0]


Out[10]:
beta     0.950279
alpha    0.000923
Name: 2013-12-31 00:00:00, dtype: float64

In [11]:
pd.DataFrame({stock: capm_analysis(prices[stock], gspc, daily_risk_free_rate).iloc[0]
              for stock in prices})


Out[11]:
AAPL FB GOOGL MSFT
beta 0.592082 0.913468 0.950279 0.870342
alpha -0.000261 0.002182 0.000923 0.000606

2 rows × 4 columns


In [12]:
capm_analysis(prices['GOOGL'], gspc, daily_risk_free_rate, 30)['beta'].plot()


Out[12]:
<matplotlib.axes.AxesSubplot at 0x7fd27d9d4650>

In [13]:
pd.DataFrame({stock: capm_analysis(prices[stock], gspc, daily_risk_free_rate, 30)['beta']
              for stock in prices}).plot()


Out[13]:
<matplotlib.axes.AxesSubplot at 0x7fd27d9bea50>

In [14]:
returns = prices.pct_change().dropna()
corr = returns.corr()
corr


Out[14]:
AAPL FB GOOGL MSFT
AAPL 1.000000 0.110946 0.107809 0.077613
FB 0.110946 1.000000 0.135778 0.068464
GOOGL 0.107809 0.135778 1.000000 0.223968
MSFT 0.077613 0.068464 0.223968 1.000000

4 rows × 4 columns


In [15]:
from statsmodels.graphics.correlation import plot_corr
plot_corr(corr, cmap='hot')
None



In [16]:
pd.scatter_matrix(returns, diagonal='kde', figsize=(10, 10))


Out[16]:
array([[<matplotlib.axes.AxesSubplot object at 0x7fd27c021b50>,
        <matplotlib.axes.AxesSubplot object at 0x7fd277fdc590>,
        <matplotlib.axes.AxesSubplot object at 0x7fd277fa6e90>,
        <matplotlib.axes.AxesSubplot object at 0x7fd277f66710>],
       [<matplotlib.axes.AxesSubplot object at 0x7fd277f366d0>,
        <matplotlib.axes.AxesSubplot object at 0x7fd277ef5650>,
        <matplotlib.axes.AxesSubplot object at 0x7fd277e44850>,
        <matplotlib.axes.AxesSubplot object at 0x7fd277daf0d0>],
       [<matplotlib.axes.AxesSubplot object at 0x7fd277d7a6d0>,
        <matplotlib.axes.AxesSubplot object at 0x7fd277db92d0>,
        <matplotlib.axes.AxesSubplot object at 0x7fd277d076d0>,
        <matplotlib.axes.AxesSubplot object at 0x7fd277cd2fd0>],
       [<matplotlib.axes.AxesSubplot object at 0x7fd277c96290>,
        <matplotlib.axes.AxesSubplot object at 0x7fd277c67250>,
        <matplotlib.axes.AxesSubplot object at 0x7fd277c261d0>,
        <matplotlib.axes.AxesSubplot object at 0x7fd277b752d0>]], dtype=object)

In [17]:
plt.scatter(returns.mean(), returns.std())
plt.xlabel('Expected returns')
plt.ylabel('Risk')
for label, x, y in zip(returns.columns, returns.mean(), returns.std()):
    plt.annotate(
        label, 
        xy = (x, y), xytext = (20, -20),
        textcoords = 'offset points', ha = 'right', va = 'bottom',
        bbox = dict(boxstyle = 'round,pad=0.5', fc = 'yellow', alpha = 0.5),
        arrowprops = dict(arrowstyle = '->', connectionstyle = 'arc3,rad=0'))